/*
 * 为了获取对象的一份拷贝，我们可以利用Object类的clone()方法：protected Object clone() throws CloneNotSupportedException。
 * 在派生类中实现Cloneable接口,这个接口没有任何的抽象方法，是一个标识接口，表明“具有某种功能”
 * 在派生类中覆盖基类的clone()方法，并声明为public。（如果派生类没有实现Cloneable接口，此方法会抛出CloneNotSupportedException）
 * 在派生类的clone()方法中，调用super.clone()。
 */
package clone;

import java.io.Serializable;

import org.apache.commons.lang.builder.ReflectionToStringBuilder;

class Student implements Cloneable/* 实现Cloneable接口,表明“能克隆 */, Serializable
{
	String name;
	int age;
	Professor p;
	
	Student(String name,int age,Professor p)
	{
		this.name=name;
		this.age=age;
		this.p=p;
	}
	
	public Object clone()//覆盖基类的clone()方法，并声明为public（注意返回类型）。
	{
		Object obj;
		try
		{
			obj=super.clone(); //调用super.clone()
		}catch(CloneNotSupportedException e)
		{
			e.printStackTrace();
			return null;
		}
		return obj;
	}
	
	@Override
	public String toString() {
		return ReflectionToStringBuilder.toString(this);
	}
}

class Professor implements Serializable
{
	String name;
	int age;
	Professor(String name,int age)
	{
		this.age=age;
		this.name=name;
	}
	
	@Override
	public String toString() {
		return ReflectionToStringBuilder.toString(this);
	}
}

class Test5
{
	public static void main(String[] args)
	{
		Professor p=new Professor("wangwu",30);
		Student s1=new Student("zhangsan",18,p);
		//Student s2=s1;
		Student s2=(Student)s1.clone();
		s2.name="lisi";
		s2.age=20;
		s2.p.age=50;
		/* 注意，对象s1中的成员Professor p是引用类型，在复制的时候，是复制的引用，会造成“一改，全改”
		 * 问题来了：String对象也是引用类型的，为什么不会产生上面的情况？
		 * Answer：String对象是->常量<-对象，当对s2.name赋值时，是先在堆内存中产生了新的String对象，再把引用传给了s2.name
		 * 而不是通过引用直接修改原来的内容。
		 */
		s2.p.name="luliu";
		System.out.println(s1);
		System.out.println(s2);
		
	}
}